feat(identity): email de «crea tu contraseña» para perfiles de donante sin contraseña#420
Open
nopestack wants to merge 5 commits into
Open
feat(identity): email de «crea tu contraseña» para perfiles de donante sin contraseña#420nopestack wants to merge 5 commits into
nopestack wants to merge 5 commits into
Conversation
…nante sin contraseña (GlobalEmergency#204) Implementa el envío real del correo de set-password que quedó como hueco en GlobalEmergency#168, más el flujo para establecer la contraseña con un token de un solo uso y caducidad. - Token opaco de 256 bits (base64url), del que solo se guarda el hash SHA-256 (tabla `password_setup_tokens`, migración 0059). Un enlace nunca queda legible en la base de datos. - `POST /auth/set-password`: valida el token (existe, no caducado, no usado), fija la contraseña, invalida el token y sus hermanos (sin replay) y devuelve un JWT (auto-login). Token inválido/caducado/usado devuelven el mismo 400 (sin oráculo). - `POST /auth/set-password/request`: reenvío del enlace; responde 202 siempre y solo envía si el email corresponde a un perfil sin contraseña (a prueba de enumeración). Ambos endpoints con rate-limit. - Plantilla de email bilingüe ES/EN a través de un puerto `EmailSender`. - Sustituye `NoopSetPasswordInviter` por `EmailSetPasswordInviter` real, que emite y persiste el token y envía el correo. El transporte por defecto registra el mensaje (queda pendiente conectar un transporte SMTP/SES real). TDD: unitarios de dominio/casos de uso e infraestructura + e2e del endpoint (token válido, caducado, ya usado, inexistente y replay). `pnpm gen:api` regenerado.
|
@nopestack is attempting to deploy a commit to the GlobalEmergency Team on Vercel. A member of the Team first needs to authorize it. |
9 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #204
Implementa el envío del correo de set-password que quedó como hueco en #168 (PR #201) y el flujo completo para que un donante que se pre-registra sin cuenta pueda crear su contraseña, acceder y ver sus donaciones.
Qué incluye
password_setup_tokens, migración0059). Caducidad configurable (PASSWORD_SETUP_TTL_HOURS, por defecto 48h).POST /auth/set-password(token + contraseña): valida el token, fija la contraseña, invalida el token y cualquier hermano pendiente del usuario (sin replay) y devuelve un JWT (auto-login).POST /auth/set-password/request(email): reenvío del enlace; responde 202 siempre y solo envía si el email es un perfil sin contraseña. Ambos endpoints con rate-limit (@Throttle).EmailSender.NoopSetPasswordInviterporEmailSetPasswordInviterreal (emite/persiste el token, arma el enlace desdeFRONTEND_URLy envía el correo).Propiedades de seguridad
randomBytes) y de un solo uso (se marcaused_at; validez =used_at IS NULL AND expires_at > now()).POST /auth/set-passwordvalida existencia + no caducado + no usado antes de permitir fijar la contraseña, e invalida el token inmediatamente tras el éxito (sin replay).Loginen este repo).Verificación
SetPassword,RequestPasswordSetup) e infraestructura (inviter real, plantilla de email), más e2e dePOST /auth/set-passwordcubriendo: token válido (200 + JWT + login posterior OK), caducado (400), ya usado (400), inexistente (400) y replay del mismo token (400).pnpm install --frozen-lockfile,pnpm --filter api build,eslint --max-warnings=0,prettier --check,pnpm --filter api test(1653 tests) y la e2e nueva.pnpm gen:apiregenerado (contrato con ambas rutas).Fuera de alcance (seguimiento)
EmailSenderpor defecto (LoggingEmailSender) registra el mensaje; conectar un transporte SMTP/SES (necesita credenciales de entrega) es el único cambio pendiente y no toca a ningún llamador.${FRONTEND_URL}/crear-contrasena?token=...; la página enapps/webque consumePOST /auth/set-passwordqueda como seguimiento (API y contrato listos).